package net.peelmeagrape.hibernate;

import net.peelmeagrape.hibernate.xmlgen.XmlAttribute;
import net.peelmeagrape.hibernate.xmlgen.XmlElement;
import net.peelmeagrape.hibernate.xmlgen.XmlText;

import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;

/**
 * Define a custom query (for use in {@link org.hibernate.Session#getNamedQuery(String)}).
 * This annotation can appear anywhere (for example on a method of a data-access-object).
 */
@Target({METHOD,FIELD,CONSTRUCTOR,TYPE,PACKAGE})
@Retention(RUNTIME)
@XmlElement(name="query", parent="hibernate-mapping")
public @interface Query
{
    @XmlText String query();

    @XmlAttribute String name();
    @XmlAttribute("flush-mode") FlushMode flushMode() default FlushMode.AUTO;
    @XmlAttribute boolean cacheable() default false;
    @XmlAttribute("cache-region") String cacheRegion() default "";
    @XmlAttribute("fetch-size") int fetchSize() default -1;
    @XmlAttribute int timeout() default -1;

    Representation[] rep() default {};

    /**
     * How should named query results be returned (e.g. POJO, XML).
     */
    @XmlElement(name="representation")
    public @interface Representation
    {
        @XmlAttribute("name") RepresentationPolicy value();
    }

    /**
     * How should named query results be returned (e.g. POJO, XML).
     */
    public enum RepresentationPolicy
    {
        POJO("pojo"),
        DOM4J("dom4j"),
        DYNAMIC_MAP("dynamic-map");
        private String value;

        RepresentationPolicy(String value)
        {
            this.value = value;
        }

        public String toString()
        {
            return value;
        }
    }

    /**
     * Flush mode for custom query.
     */
    public enum FlushMode
    {
        AUTO("auto"),
        NEVER("never"),
        ALWAYS("always");
        private String value;

        FlushMode(String value)
        {
            this.value = value;
        }

        public String toString()
        {
            return value;
        }
    }
}
